package com.wuzhun.wxmp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wuzhun.wxmp.common.ResultCode;
import com.wuzhun.wxmp.common.ServiceException;
import com.wuzhun.wxmp.constant.CommonConstant;
import com.wuzhun.wxmp.mapper.AdminUserMapper;
import com.wuzhun.wxmp.model.entity.OperateLog;
import com.wuzhun.wxmp.service.IAdminUserService;
import com.wuzhun.wxmp.service.IOperateLogService;
import com.wuzhun.wxmp.util.DateTimeUtil;
import com.wuzhun.wxmp.util.StringUtil;
import com.wuzhun.wxmp.model.entity.AdminUser;
import com.wuzhun.wxmp.model.dto.admin.AdminUserDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 管理员表 服务实现类
 * </p>
 *
 * @author renbaolin
 * @since 2022-12-05
 */
@Service
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements IAdminUserService {

    @Resource
    private AdminUserMapper adminUserMapper;
    @Resource
    private IOperateLogService operateLogService;

    @Override
    public AdminUserDTO queryUserAndCheckPassword(String ip, String username, String password) {
        loginCheck(ip);
        AdminUser adminUser = adminUserMapper.selectOne(new QueryWrapper<AdminUser>().eq("username", username));
        if (adminUser == null) {
            throw new ServiceException(ResultCode.USERNAME_NOT_EXIST);
        }
        if (adminUser.getPasswordExpireTime().before(new Date())) {
            throw new ServiceException(ResultCode.PASSWORD_EXPIRE);
        }
        if (!verifyPassword(password, adminUser)) {
            throw new ServiceException(ResultCode.USERNAME_OR_PASSWORD_WRONG);
        }
        return convertAdminUser(adminUser);
    }

    @Override
    public AdminUserDTO queryUserByUid(Integer uid) {
        return convertAdminUser(adminUserMapper.selectOne(new QueryWrapper<AdminUser>().eq("id", uid)));
    }

    @Override
    public Boolean editPassword(Integer uid, String oldPassword, String newPassword, String repeatPassword) {
        AdminUser adminUser = adminUserMapper.selectOne(new QueryWrapper<AdminUser>().eq("id", uid));
        if (adminUser == null) {
            throw new ServiceException(ResultCode.USERNAME_NOT_EXIST);
        }
        if (Objects.equals(oldPassword, newPassword)) {
            throw new ServiceException(ResultCode.OLD_PASSWORD_NEW_PASSWORD_SAME);
        }
        if (!verifyPassword(oldPassword, adminUser)) {
            throw new ServiceException(ResultCode.OLD_PASSWORD_WRONG);
        }
        if (newPassword.length() < CommonConstant.PASSWORD_MIN_LENGTH) {
            throw new ServiceException(ResultCode.NEW_PASSWORD_MIN_WRONG);
        }
        if (newPassword.length() > CommonConstant.PASSWORD_MAX_LENGTH) {
            throw new ServiceException(ResultCode.NEW_PASSWORD_MAX_WRONG);
        }
        if (!newPassword.equals(repeatPassword)) {
            throw new ServiceException(ResultCode.NEW_PASSWORD_WRONG);
        }
        AdminUser newAdminUser = new AdminUser();
        newAdminUser.setId(uid);
        newAdminUser.setPassword(StringUtil.getMd5Password(newPassword, adminUser.getSalt()));
        // 密码有效期
        newAdminUser.setPasswordExpireTime(DateTimeUtil.getDateByIncreaseDay(CommonConstant.PASSWORD_EXPIRE_DAY));
        return adminUserMapper.updateById(newAdminUser) > 0;
    }

    @Override
    public AdminUserDTO getOneByUsername(String username) {
        AdminUser adminUser = adminUserMapper.selectOne(new QueryWrapper<AdminUser>().eq("username", username));
        return convertAdminUser(adminUser);
    }

    /**
     * 校验密码
     *
     * @param password
     * @param adminUser
     * @return
     */
    private boolean verifyPassword(String password, AdminUser adminUser) {
        return StringUtil.getMd5Password(password, adminUser.getSalt()).equals(adminUser.getPassword());
    }

    /**
     * 用户类型转换
     *
     * @param adminUser
     * @return
     */
    private AdminUserDTO convertAdminUser(AdminUser adminUser) {
        if (adminUser == null) {
            return null;
        }
        AdminUserDTO adminUserDTO = new AdminUserDTO();
        adminUserDTO.setUsername(adminUser.getUsername());
        adminUserDTO.setNickname(adminUser.getNickname());
        adminUserDTO.setUid(adminUser.getId());
        adminUserDTO.setStatus(adminUser.getStatus());
        adminUserDTO.setPasswordExpireTime(adminUser.getPasswordExpireTime());
        return adminUserDTO;
    }

    /**
     * 登录校验
     *
     * @param ip
     */
    private void loginCheck(String ip) {
        QueryWrapper<OperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("url", "/admin/user/login").eq("return_code", ResultCode.USERNAME_OR_PASSWORD_WRONG.getErrorCode());
        queryWrapper.ge("created_time", DateTimeUtil.getDateStartTime(new Date()));
        queryWrapper.le("created_time", DateTimeUtil.getDateEndTime(new Date()));
        queryWrapper.orderByDesc("created_time");
        List<OperateLog> operateLogList  = operateLogService.list(queryWrapper);
        // 登录密码错误超过5锁定30分钟
        if (CollectionUtils.isNotEmpty(operateLogList) && operateLogList.size() > 5 && operateLogList.get(0).getCreatedTime().after(DateTimeUtil.getDateByIncreaseMinute(-30))) {
            throw new ServiceException(ResultCode.LOGIN_LOCKED);
        }
    }
}
